#pragma once

#include <iostream>
#include <cmath>

class Vec2
{
public:
    float  x, y;

    Vec2( float s = float(0.0)) :
		x(s), y(s)
	{
		//
	}

    Vec2( float x, float y ) :
		x(x), y(y)
	{
		//
	}

    Vec2( const Vec2& v )
	{
		x = v.x;
		y = v.y;
	}

    float& operator [] ( int i ) { return *(&x + i); }
    const float operator [] ( int i ) const { return *(&x + i); }

	float dot( const Vec2& v ) const
	{
		return x*v.x + y*v.y;
	}

	float length() const
	{
		return std::sqrt( dot(*this) );
	}

	Vec2& normalize()
	{
		*this /= length();
		return *this;
	}

    Vec2 operator - () const
	{
		return Vec2( -x, -y );
	}

    Vec2 operator + ( const Vec2& v ) const
	{
		return Vec2( x + v.x, y + v.y );
	}

    Vec2 operator - ( const Vec2& v ) const
	{
		return Vec2( x - v.x, y - v.y );
	}

    Vec2 operator * ( const float s ) const
	{
		return Vec2( s*x, s*y );
	}

    Vec2 operator * ( const Vec2& v ) const
	{
		return Vec2( x*v.x, y*v.y );
	}

    friend Vec2 operator * ( const float s, const Vec2& v )
	{
		return v * s;
	}

    Vec2 operator / ( const float s ) const
	{
		float r = float(1.0) / s;
		return *this * r;
    }

    Vec2& operator += ( const Vec2& v )
	{
		x += v.x;
		y += v.y;
		return *this;
	}

    Vec2& operator -= ( const Vec2& v )
	{
		x -= v.x;
		y -= v.y;
		return *this;
	}

    Vec2& operator *= ( const float s )
	{
		x *= s;
		y *= s; 
		return *this;
	}

    Vec2& operator *= ( const Vec2& v )
	{
		x *= v.x;
		y *= v.y; 
		return *this;
	}

    Vec2& operator /= ( const float s )
	{
		float r = float(1.0) / s;
		*this *= r;

		return *this;
    }
	
    friend std::ostream& operator << ( std::ostream& os, const Vec2& v )
	{
		return os << "( " << v.x << ", " << v.y <<  " )";
    }

    friend std::istream& operator >> ( std::istream& is, Vec2& v )
	{
		return is >> v.x >> v.y ;
	}

    operator const float* () const
	{
		return static_cast<const float*>( &x );
	}

    operator float* ()
	{
		return static_cast<float*>( &x );
	}
};